package com.huatai.bpmn.utils;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huatai.bpmn.controller.BasicLoadController;
import com.huatai.bpmn.entity.ExternalParameterEntity;
import com.huatai.bpmn.entity.FileEntity;
import com.huatai.bpmn.entity.TbBusinessEntity;
import com.huatai.bpmn.service.*;
import com.huatai.common.api.R;
import com.huatai.common.util.AuthUtil;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.transaction.annotation.Transactional;
import springfox.documentation.spring.web.json.Json;

import java.io.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipInputStream;

/**
 * @Author: nzj
 * @Date: 2023/7/7 14:11
 */
public class Activiti7Util {

	private Activiti7Util(){}

	public static final ProcessEngine PROCESS_ENGINE = ProcessEngines.getDefaultProcessEngine();

	/**
	 * 资源管理类
	 */
	public static final RepositoryService repositoryService = PROCESS_ENGINE.getRepositoryService();

	/**
	 * 运行时管理类
	 */
	public static final RuntimeService runtimeService = PROCESS_ENGINE.getRuntimeService();

	/**
	 * 任务管理类
	 */
	public static final TaskService taskService = PROCESS_ENGINE.getTaskService();

	/**
	 * 历史数据管理类
	 */
	public static final HistoryService historyService = PROCESS_ENGINE.getHistoryService();


	/**
	 * 流程部署-- 通过zip包进行bpmn文件部署
	 *
	 * @param zipPath: zip文件的路径 带[.zip] 后缀
	 * @param name:    给部署起一个名字
	 */
	public static Map<String, Object> importProcessByZip(String zipPath, String name)
		throws FileNotFoundException {
		FileInputStream fileInputStream = new FileInputStream(zipPath);
		ZipInputStream stream = new ZipInputStream(fileInputStream);
		Deployment deploy =
			repositoryService
				.createDeployment()
				.addZipInputStream(stream)
				.name(name)
				.deploy();
		return getMap(deploy);
	}

	private static Map<String, Object> getMap(Deployment deploy) {
		Map<String, Object> map = new HashMap<>(4);
		// 部署id
		map.put("deploymentId", deploy.getId());
		// 部署名称
		map.put("deploymentName", deploy.getName());
		// 部署时间
		map.put("deploymentTime", deploy.getDeploymentTime());
		return map;
	}

	/**
	 * 查询流程定义集合【流程定义模板列表】
	 *
	 * @param key bpmn文件中的 processId processId = null 则查全部模板
	 */
	public static List<Map<String, Object>> queryProcessDefinition(String key) {
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
		if (key != null) {
			// 根据指定key查出模板
			query.processDefinitionKey(key);
		}
		List<Map<String, Object>> result = new ArrayList<>();
		List<ProcessDefinition> list = query.list();
		for (ProcessDefinition processDefinition : list) {
			Map<String, Object> map = new HashMap<>(8);
			// 流程部署id
			map.put("deploymentId", processDefinition.getDeploymentId());
			// 流程定义id
			map.put("processDefinitionId", processDefinition.getId());
			// 流程定义key
			map.put("processDefinitionKey", processDefinition.getKey());
			// 流程定义名称
			map.put("processDefinitionName", processDefinition.getName());
			// 流程定义版本
			map.put("processDefinitionVersion", processDefinition.getVersion());
			result.add(map);
		}
		return result;
	}

	/**
	 * 删除流程部署信息
	 *
	 * @param deploymentId 流程部署id
	 * @param cascade:     true-连同已经存在的运行任务一起删除 false-不删除运行的任务
	 * @author zh
	 */
	public static void deleteProcessDefinition(String deploymentId, boolean cascade) {
		repositoryService.deleteDeployment(deploymentId, cascade);
	}

	/**
	 * 根据指定的bpmn的 processId 下载已经存在数据库中的文件 需要 common-io.jar
	 *
	 * @param key          bpmn文件中的 processId
	 * @param imgSavePath  需要把对应的图片文件保存的绝对路径【例：D:/bpmn/test-image.png】
	 * @param bpmnSavePath 需要把对应的bpmn文件保存的绝对路径【例：D:/bpmn/test-bpmn.bpmn】
	 */
	public static void downDeployment(String key, String imgSavePath, String bpmnSavePath) {
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
		// 根据指定key查出模板
		query.processDefinitionKey(key);
		for (ProcessDefinition processDefinition : query.list()) {
			//    拿到deploymentId
			String deploymentId = processDefinition.getDeploymentId();
			// 图片目录和名称
			String pngName = processDefinition.getDiagramResourceName();
			InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, pngName);
			String bpmnName = processDefinition.getResourceName();
			InputStream bpmnNameResourceAsStream =
				repositoryService.getResourceAsStream(deploymentId, bpmnName);
			File pngFile = new File(imgSavePath);
			File bpmnFile = new File(bpmnSavePath);
			FileOutputStream pngFileOutputStream = null;
			FileOutputStream bpmnFileOutputStream = null;
			try {
				pngFileOutputStream = new FileOutputStream(pngFile);
				bpmnFileOutputStream = new FileOutputStream(bpmnFile);
				IOUtils.copy(resourceAsStream, pngFileOutputStream);
				IOUtils.copy(bpmnNameResourceAsStream, bpmnFileOutputStream);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				// 关闭流输入流
				try {
					resourceAsStream.close();
					bpmnNameResourceAsStream.close();
					assert pngFileOutputStream != null;
					assert bpmnFileOutputStream != null;
					// 关闭流输出流
					pngFileOutputStream.close();
					bpmnFileOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 开启一个流程实例
	 *
	 * @param processDefinitionId 流程定义id
	 * @param
	 * @param params:  key:在bpmn文件中定义的变量占位符【例： ${userName}】 value:对应的占位值 【例： 小明】
	 * @author zh
	 */
	@Transactional(rollbackFor = Exception.class)
	public static R<Map<String, Object>> startProcessInstanceByKey(String processDefinitionId, JSONObject params, TbBusinessService businessService
		, FileService fileService, BasicLoadService basicLoadService, ExternalParameterService externalParameterService) {
		String formKey = params.getString("formKey");
		//根据key来查询部署的id和部署的key
		ProcessDefinition definitionKey = Activiti7Util.repositoryService.createProcessDefinitionQuery()
			.processDefinitionKey(params.getString("definitionKey")).latestVersion().singleResult();
		Long businessKey = IdWorker.getId();
		//获取流程定义的绑定外部参数
//		JSONArray bindingParamArray = params.getJSONArray("param");
//		List<JSONObject> jsonObjects = bindingParamArray.toJavaList(JSONObject.class);
//		HashMap<String, Object> bindingParamMap = jsonObjectArrayToMap(jsonObjects);

//		basicDataService.addList(jsonObjects,businessKey.toString());
		//流程定义用户id
		//获取表单中的表单数据与表单内容数据
		String fqrId = AuthUtil.getUser().getUserId().toString();
		JSONObject param = params.getJSONObject("param");
		param.put("fqrId",fqrId);
		JSONObject extendJson = new JSONObject(2);
		extendJson.put("data",params.getJSONObject("data"));
		extendJson.put("param", param);
		//获取表单数据
//		JSONObject jsonObject = params.getJSONObject("data");
//		String place = jsonObject.getJSONArray("place1").getJSONObject(0).getString("place");
		// 根据流程定义ID启动流程
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey.toString(),extendJson.getJSONObject("param"));

		//遍历表单数据(jsonObject)转换成map集合进行存储
//		HashMap<String, List<JSONObject>> resultMap = jsonObjectToMap(jsonObject);
//		basicLoadService.addList(resultMap,processInstance.getId());
		String matterName = params.getString("matterName");
		//保存上传的文件路径
		JSONArray files = params.getJSONArray("files")==null?new JSONArray():params.getJSONArray("files");
		for (int i = 0; i <files.size() ; i++) {
			JSONObject file = files.getJSONObject(i);
			String fileType = file.getString("fileType");
			String path = file.getString("path");
			LambdaQueryWrapper<FileEntity> fileQuery = Wrappers.lambdaQuery();
			fileQuery
				.eq(FileEntity::getFilePath,path)
				.eq(FileEntity::getFileType,fileType);
			FileEntity fileEntity = new FileEntity();
			fileEntity.setDeleted(false);
			fileEntity.setBusinessKey(processInstance.getId());
			fileService.update(fileEntity,fileQuery);
		}

		/*ExternalParameterEntity externalParameterEntity = externalParameterService.getById(formKey);
		//将业务数据进行存储
		//表单数据
		basicLoadService.add(params.getJSONObject("param"),externalParameterEntity.getPlace(),String.valueOf(businessKey));
		//表格数据
		JSONObject data = params.getJSONObject("data");
		Set<String> keySet = data.keySet();
		for (String s : keySet) {
			JSONArray jsonArray = data.getJSONArray(s);
			for (int i = 0; i <jsonArray.size() ; i++) {
				basicLoadService.add(jsonArray.getJSONObject(i),s,String.valueOf(businessKey));
			}
			*//*List<Map> maps = JSONObject.parseArray(arr, Map.class);
			List<JSONObject> list = JSONObject.parseArray(arr, JSONObject.class);
			for (JSONObject jsonObject : list) {
				basicLoadService.add(jsonObject,s);
			}*//*
		}*/
		//将流程实例添加到业务流水表
		TbBusinessEntity business = new TbBusinessEntity();
		business.setCreateUserid(fqrId);
		business.setId(businessKey);
		business.setProcinstId(processInstance.getId());
		business.setStatus(0);
		business.setExtend(extendJson);
		business.setMatterName(matterName);
		business.setDeleted(0);
		//todo 后期可能进行修改
//		business.setExternalParameterId(place);null
		business.setDeployId(definitionKey.getDeploymentId());
		business.setDeployKey(definitionKey.getKey());
		businessService.save(business);
		Map<String, Object> map = new HashMap<>(4);
		// 流程定义id
		map.put("processDefinitionId", processInstance.getProcessDefinitionId());
		// 流程实例id
		map.put("processInstanceId", processInstance.getId());
		return R.data(map);
	}

	private  static HashMap<String, Object>  jsonObjectArrayToMap(List<JSONObject> jsonObjects) {
		HashMap<String, Object> map = new HashMap<>();
		for (JSONObject jsonObject : jsonObjects) {
			String external_parameter_key = jsonObject.getString("external_parameter_key");
			String external_parameter_value = jsonObject.getString("external_parameter_value");
			map.put(external_parameter_key,external_parameter_value);
		}
		return map;
	}

	/**
	 * 	遍历表单数据(jsonObjec)转换成map集合进行存储
	 * @param jsonObject
	 */
	private static HashMap<String, List<JSONObject>> jsonObjectToMap(JSONObject jsonObject) {
		HashMap<String, List<JSONObject>> map = new HashMap<>();
		for (String place:jsonObject.keySet()){
			JSONArray jsonArray = jsonObject.getJSONArray(place);
			List<JSONObject> list = jsonArray.toJavaList(JSONObject.class);
			map.put(place,list);
		}
		return map;
	}



	/**
	 * 开启一个流程实例
	 *
	 * @param processDefinitionId 流程定义id
	 * @param businessKey         可以绑定一个自定义的业务id
	 * @author zh
	 */
	public static Map<String, Object> startProcessInstanceByKey(
		String processDefinitionId, String businessKey) {
		// 根据流程定义ID启动流程
		ProcessInstance one;
		if(StringUtils.isBlank(businessKey)){
			one = runtimeService.startProcessInstanceByKey(processDefinitionId);
		}else {
			one = runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey);
		}
		Map<String, Object> map = new HashMap<>(4);
		// 流程定义id
		map.put("processDefinitionId", one.getProcessDefinitionId());
		// 流程实例id
		map.put("id", one.getId());
		// 当前活动id
		map.put("activityId", one.getActivityId());
		return map;
	}

	/**
	 * 【如果某个任务设置了负责人】则可通过该方法查询负责人【根据人名查出 自己有哪些任务待完成】
	 *
	 * @param key       bpmn里面的id值
	 * @param assignee:负责人名
	 * @author zh
	 */
	public static List<Map<String, Object>> taskListByAssignee(String key, String assignee) {
		// 获取已经运行的任务列表
		List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee).list();
		return getMaps(taskList);
	}

	/**
	 * 【如果某个任务设置了候选人】则可通过该方法查询候选人【根据人名查出 自己有哪些任务待完成】
	 *
	 * @param key                bpmn里面的id值
	 * @param candidateUserName: 候选人名
	 * @author zh
	 */
	public static List<Map<String, Object>> taskListByCandidateUser(String key, String candidateUserName) {
		// 获取 已经运行的任务列表
		List<Task> taskList = taskService.createTaskQuery().processDefinitionKey(key).taskCandidateUser(candidateUserName).list();
		return getMaps(taskList);
	}

	private static List<Map<String, Object>> getMaps(List<Task> taskList) {
		List<Map<String, Object>> result = new ArrayList<>();
		for (Task task : taskList) {
			Map<String, Object> map = new HashMap<>(8);
			// 流程实例id
			map.put("processInstanceId", task.getProcessInstanceId());
			// 任务id
			map.put("id", task.getId());
			// 任务负责人
			map.put("assignee", task.getAssignee());
			// 任务名称
			map.put("name", task.getName());
			// 任务创建时间
			map.put("createTime", task.getCreateTime());
			result.add(map);
		}
		return result;
	}

	/**
	 *  添加候选人
	 *
	 *@param taskId 任务id
	 *@param userId 候选人
	 *@author zh
	 */
	public static void addGroupUser(String taskId, String userId){
		taskService.addCandidateUser(taskId, userId);
	}

	/**
	 *  删除候选人
	 *
	 *@param taskId 任务id
	 *@param userId 候选人
	 *@author zh
	 */
	public static void deleteGroupUser(String taskId, String userId){
		taskService.deleteCandidateUser(taskId, userId);
	}

	/**
	 * 【如果某个任务设置了候选人】 某个负责人进行拾取任务【通过任务id和人名 开始拾取任务】
	 *
	 * @param taskId：           任务id
	 * @param
	 * @return true-拾取成功 false=拾取失败
	 * @author zh
	 */
	public static boolean claimTask(String taskId, UserDetails userDetails) {
		// 根据条件 查出任务
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
//        List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(taskId);
		// 能查到任务并且 传入参数也符合候选人 才能进行拾取
		if (task != null && isCandidate(taskId, userDetails)) {
			// 进行拾取操作 其实就是把指定任务的assignee设置对应的负责人名
			taskService.claim(task.getId(), userDetails.getUsername());
			return true;
		}
		return false;
	}

	/**
	 * 判断指定任务的候选人名单中是否有： candidateUserName
	 *
	 * @return true:是候选人 false：不是候选人
	 */
	private static boolean isCandidate(String taskId, UserDetails userDetails) {

		for (IdentityLink link : taskService.getIdentityLinksForTask(taskId)) {
			if (userDetails.getUsername().equals(link.getUserId())) {
				return true;
			}
			Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
			List<String> roleIds = authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
			if (roleIds.contains(link.getGroupId())){
				return true;
			}
		}
		return false;
	}

	/**
	 * [描述]【如果某个任务设置了候选人】 负责人已经拾取某个任务以后 打算再归还回去
	 *
	 * @param taskId：           任务id
	 * @param candidateUserName 候选人名
	 * @author zh
	 */
	public static boolean claimTaskReturn(String taskId, String candidateUserName) {
		// 根据条件 查出任务
		Task task =
			taskService
				.createTaskQuery()
				.taskId(taskId)
				.taskCandidateUser(candidateUserName)
				.singleResult();
		if (task != null) {
			// 归还操作 其实就是把该任务的 assignee 设置成null
			taskService.setAssignee(task.getId(), null);
			return true;
		}
		return false;
	}

	/**
	 * 【如果某个任务设置了候选人】某个任务虽然是自己的 但是可以交给其他人进行完成
	 *
	 * @param taskId：           任务id
	 * @param candidateUserName 候选人名
	 * @param assigneeName：     交接人
	 * @author zh
	 */
	public static boolean taskHandover(String taskId, String candidateUserName, String assigneeName) {
		// 根据条件 查出任务
		Task task =
			taskService
				.createTaskQuery()
				.taskId(taskId)
				.taskCandidateUser(candidateUserName)
				.singleResult();
		// 交接操作 这个任务是自己虽然是候选人 但是 可以直接把这个任务交接给别人进行完成
		if (task != null) {
			taskService.setAssignee(task.getId(), assigneeName);
			return true;
		}
		return false;
	}

	/**
	 * 根据名字 查询个人待执行的任务【已经把任务拾取了】【带分页】
	 *
	 * @param taskAssignName 人名【例：班长、经理、总经理等...】
	 * @param key            bpmn文件中的processId
	 * @param firstResult    当前页【默认从0开始】
	 * @param maxResults     页长
	 */
	public static List<Map<String, Object>> taskListByMy(
		String taskAssignName, String key, Integer firstResult, Integer maxResults) {
		List<Task> list =
			taskService
				.createTaskQuery()
				.processDefinitionKey(key)
				.taskAssignee(taskAssignName)
				.listPage(firstResult, maxResults);
		List<Map<String, Object>> result = new ArrayList<>();
		for (Task task : list) {
			Map<String, Object> taskMap = new HashMap<>(8);
			// 任务id
			taskMap.put("taskId", task.getId());
			// 任务名称
			taskMap.put("taskName", task.getName());
			// 创建时间
			taskMap.put("createTime", task.getCreateTime());
			// 任务负责人
			taskMap.put("taskAssignee", task.getAssignee());
			// 流程实例id
			taskMap.put("processInstanceId", task.getProcessInstanceId());
			result.add(taskMap);
		}
		return result;
	}

	/**
	 * 完成个人任务
	 *
	 * @param taskAssignName： 任务代理人
	 * @param taskId：         任务id params: 流程连接线上的变量 【例】假如流程线上面有一个变量名 ${audit=='通过'}
	 *                        则调用时候：params.put("audit","通过"); 这里执行时，会判断控制线的变量 从而控制流程走向
	 */

	public static boolean completeTask(String taskAssignName, String taskId, Map<String, Object> params) {
		try {
			Task task = taskService.createTaskQuery().taskId(taskId).taskAssignee(taskAssignName).singleResult();
			if (task == null) {
				// 说明根据任务id和人名 无法查到待办的指定任务
				return false;
			}
			taskService.complete(taskId, params);
			return true;
		} catch (ActivitiException ee) {
			ee.printStackTrace();
			//流程线上已经绑定变量了
			return false;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("【error】 执行报错： " + e.getMessage());
			return false;
		}
	}


	/**
	 * 先执行拾取任务，再进行完成任务。
	 *
	 * @author zh
	 */
	public static boolean claimTaskAndCompleteTask(String taskId, UserDetails userDetails, Map<String, Object> params) {
		if (claimTask(taskId, userDetails)) {
			completeTask(userDetails.getUsername(), taskId, params);
			return true;
		}
		return false;
	}

	/**
	 * 根据相应的条件 查出历史的任务信息
	 *
	 * @param processDefinitionId： 流程定义id
	 * @param processInstanceId：   流程实例id
	 * @param assigneeName：        代理人名
	 * @author zh
	 */
	public static List<HistoricActivityInstance> historicActivityInstanceList(
		String processDefinitionId, String processInstanceId, String assigneeName) {
		// 例子：查询 act_hi_actinst 表中数据
		HistoricActivityInstanceQuery instanceQuery =
			historyService.createHistoricActivityInstanceQuery();
		if (processDefinitionId != null) {
			// 查询条件： 根据流程定义id 拿到数据
			instanceQuery.processDefinitionId(processDefinitionId);
		}
		if (processInstanceId != null) {
			// 查询条件： 根据流程实例id 拿到数据
			instanceQuery.processInstanceId(processInstanceId);
		}
		if (assigneeName != null) {
			instanceQuery.taskAssignee(assigneeName);
		}
		return instanceQuery.list();
	}

	/**
	 * 通过流程定义id --》 [挂起【暂停】] 或 [激活【启动】] 全部流程实例的执行
	 *
	 * @author zh
	 */
	public static void suspendAllProcessInstance(String key) {
		// 通过指定的key 获取单个流程定义
		ProcessDefinition processDefinition =
			repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).singleResult();
		// 判断指定的流程定义 是否挂起 true=挂起  false=激活
		boolean suspended = processDefinition.isSuspended();
		// 拿到流程定义id
		String processDefinitionId = processDefinition.getId();
		if (suspended) {
			// 说明原来是挂起的 则可以对流程定义和旗下的所有流程实例进行激活操作
			//    参数说明：processDefinitionId=流程定义id 、 activateProcessInstances=挂起或者激活、activationDate=执行事件
			repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
			System.out.println("对流程定义id为" + processDefinitionId + ",进行[激活]操作");
		} else {
			// 说明原来是激活的 则可以对流程定义和旗下的所有流程实例进行挂起操作
			repositoryService.activateProcessDefinitionById(processDefinitionId, false, null);
			System.out.println("对流程定义id为" + processDefinitionId + ",进行[挂起]操作");
		}
		System.out.println("流程定义" + processDefinition.getName() + "已经操作成功【包括关联的所有实例】");
	}

	/**
	 * 针对某一个流程实例进行【挂起】或【激活】操作
	 *
	 * @author zh
	 */
	public static void suspendProcessInstanceByProcessInstanceId(String processInstanceId) {
		ProcessInstance instance =
			runtimeService
				.createProcessInstanceQuery()
				.processInstanceId(processInstanceId)
				.singleResult();
		// 原来是挂起的
		if (instance.isSuspended()) {
			runtimeService.activateProcessInstanceById(instance.getId());
			System.out.println("流程实例id=" + instance.getId() + "，已激活");
		} else {
			runtimeService.suspendProcessInstanceById(instance.getId());
			System.out.println("流程实例id=" + instance.getId() + "，已挂起");
		}
		System.out.println("单个流程实例：" + instance.getName() + "，已经操作成功");
	}

	public static R<Map<String, Object>> startTask(String processDefinitionId, JSONObject params, TbBusinessService businessService
		, FileService fileService, BasicLoadService basicLoadService, ExternalParameterService externalParameterService){
		String definitionKey = params.getString("definitionKey");
		//1.获得engine对象
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		//2.获得RepositoryService
		RepositoryService repositoryService = engine.getRepositoryService();
		//3.根据部署id来获得流程定义
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
			.deploymentId(definitionKey).singleResult();
		//4.获得RuntimeService
		RuntimeService runtimeService = engine.getRuntimeService();
		//5.根据流程定义（类）生成流程实例（对象），借助RuntimeService
		System.out.println("processDefinition:"+processDefinition);
		ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());
		//6.打印流程实例中的信息
		System.out.println("流程定义的id:"+processInstance.getProcessDefinitionId());
		System.out.println("实例id:"+processInstance.getId());
		return R.data(null);
	}
}
